import axios from 'axios'
import config from '../config'
import { Base64 } from 'js-base64'
import interceptors from './interceptors'

axios.defaults.withCredentials = true
//创建默认的axios实例
const defaultAxios = axios.create({
  baseURL: config.serviceBaseURL
})
//创建另一个axios实例，专门用来请求oauth2认证接口
const anotherAxios = axios.create({
  baseURL: config.serviceBaseURL
})
anotherAxios.interceptors.request.use(interceptors.requestInterceptor)
anotherAxios.interceptors.response.use(...interceptors.responseInterceptor())

/**
 * 认证函数
 * @param {*} data 
 * @returns 
 */
function auth(data) {
  return new Promise((resolve, reject) => {
    anotherAxios({
      method: 'POST',
      url: '/oauth2/token',
      headers: {
        // 这里要创建一个Basic认证头，用appid和appsecret进行base64编码
        // 也就是说，请求认证接口都还需要一个Basic认证，不是想请求就请求的。appid和appsecret是由后端分配的，前端自己保存好
        // 如果对接过一些开放平台的接口，对appid和appsecret这两个东西应该不会陌生
        'Authorization': encodeBasicAuth()
      },
      data
    }).then(respdata => {
      const {
        access_token, // 访问令牌
        refresh_token, // 刷新令牌
        expires_in // 访问令牌还有多少秒过期
      } = respdata
      localStorage.setItem('access_token', access_token)
      localStorage.setItem('refresh_token', refresh_token)
      localStorage.setItem('expire', expires_in + (Date.now() / 1000)) // 保存访问令牌的过期时间戳
      resolve(respdata)
    }).catch(err => {
      reject(err)
    })
  })
}

function encodeBasicAuth() {
  return `Basic ${Base64.encode(`${config.appId}:${config.appSecret}`)}`
}

defaultAxios.interceptors.request.use(async request => {
  interceptors.requestInterceptor(request)
  let access_token = localStorage.getItem('access_token')
  if (access_token) {
    const expire = localStorage.getItem('expire')
    // 我这里是提前10秒刷新，防止一些网络波动的情况
    if (expire && expire - 10 <= Date.now() / 1000) {
      try {
        const refresh_token = localStorage.getItem('refresh_token')
        // 刷新访问令牌
        const respdata = await auth({
          grant_type: 'refresh_token',
          refresh_token
        })
        access_token = respdata.access_token
      } catch (err) {
        // 刷新令牌都过期了，必须让用户重新手动登录
        if (err.status === 401) {
          alert('登录过期，请重新登录')
          // 跳转到登录页面或者其它处理逻辑
        }
      }
    }

    request.headers['Authorization'] = `Bearer ${access_token}`
  }

  return request
})

defaultAxios.interceptors.response.use(...interceptors.responseInterceptor())

defaultAxios.auth = auth
export default defaultAxios